home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / fileutil / fileutils-3.16.tar.gz / fileutils-3.16.tar / fileutils-3.16 / lib / getline.c < prev    next >
C/C++ Source or Header  |  1996-07-14  |  4KB  |  156 lines

  1. /* getline.c -- Replacement for GNU C library function getline
  2.  
  3. Copyright (C) 1993, 1996 Free Software Foundation, Inc.
  4.  
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the
  8. License, or (at your option) any later version.
  9.  
  10. This program is distributed in the hope that it will be useful, but
  11. WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  18.  
  19. /* Written by Jan Brittenson, bson@gnu.ai.mit.edu.  */
  20.  
  21. #if HAVE_CONFIG_H
  22. # include <config.h>
  23. #endif
  24.  
  25. /* The `getdelim' function is only declared if the following symbol
  26.    is defined.  */
  27. #define _GNU_SOURCE    1
  28. #include <stdio.h>
  29. #include <sys/types.h>
  30.  
  31. #if defined __GNU_LIBRARY__ && HAVE_GETDELIM
  32.  
  33. int
  34. getline (lineptr, n, stream)
  35.      char **lineptr;
  36.      size_t *n;
  37.      FILE *stream;
  38. {
  39.   return getdelim (lineptr, n, '\n', stream);
  40. }
  41.  
  42.  
  43. #else /* ! have getdelim */
  44.  
  45. # define NDEBUG
  46. # include <assert.h>
  47.  
  48. # if STDC_HEADERS
  49. #  include <stdlib.h>
  50. # else
  51. char *malloc (), *realloc ();
  52. # endif
  53.  
  54. /* Always add at least this many bytes when extending the buffer.  */
  55. # define MIN_CHUNK 64
  56.  
  57. /* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
  58.    + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from
  59.    malloc (or NULL), pointing to *N characters of space.  It is realloc'd
  60.    as necessary.  Return the number of characters read (not including the
  61.    null terminator), or -1 on error or EOF.  */
  62.  
  63. int
  64. getstr (lineptr, n, stream, terminator, offset)
  65.      char **lineptr;
  66.      size_t *n;
  67.      FILE *stream;
  68.      char terminator;
  69.      size_t offset;
  70. {
  71.   int nchars_avail;        /* Allocated but unused chars in *LINEPTR.  */
  72.   char *read_pos;        /* Where we're reading into *LINEPTR. */
  73.   int ret;
  74.  
  75.   if (!lineptr || !n || !stream)
  76.     return -1;
  77.  
  78.   if (!*lineptr)
  79.     {
  80.       *n = MIN_CHUNK;
  81.       *lineptr = malloc (*n);
  82.       if (!*lineptr)
  83.     return -1;
  84.     }
  85.  
  86.   nchars_avail = *n - offset;
  87.   read_pos = *lineptr + offset;
  88.  
  89.   for (;;)
  90.     {
  91.       register int c = getc (stream);
  92.  
  93.       /* We always want at least one char left in the buffer, since we
  94.      always (unless we get an error while reading the first char)
  95.      NUL-terminate the line buffer.  */
  96.  
  97.       assert(*n - nchars_avail == read_pos - *lineptr);
  98.       if (nchars_avail < 2)
  99.     {
  100.       if (*n > MIN_CHUNK)
  101.         *n *= 2;
  102.       else
  103.         *n += MIN_CHUNK;
  104.  
  105.       nchars_avail = *n + *lineptr - read_pos;
  106.       *lineptr = realloc (*lineptr, *n);
  107.       if (!*lineptr)
  108.         return -1;
  109.       read_pos = *n - nchars_avail + *lineptr;
  110.       assert(*n - nchars_avail == read_pos - *lineptr);
  111.     }
  112.  
  113.       if (c == EOF || ferror (stream))
  114.     {
  115.       /* Return partial line, if any.  */
  116.       if (read_pos == *lineptr)
  117.         return -1;
  118.       else
  119.         break;
  120.     }
  121.  
  122.       *read_pos++ = c;
  123.       nchars_avail--;
  124.  
  125.       if (c == terminator)
  126.     /* Return the line.  */
  127.     break;
  128.     }
  129.  
  130.   /* Done - NUL terminate and return the number of chars read.  */
  131.   *read_pos = '\0';
  132.  
  133.   ret = read_pos - (*lineptr + offset);
  134.   return ret;
  135. }
  136.  
  137. int
  138. getline (lineptr, n, stream)
  139.      char **lineptr;
  140.      size_t *n;
  141.      FILE *stream;
  142. {
  143.   return getstr (lineptr, n, stream, '\n', 0);
  144. }
  145.  
  146. int
  147. getdelim (lineptr, n, delimiter, stream)
  148.      char **lineptr;
  149.      size_t *n;
  150.      int delimiter;
  151.      FILE *stream;
  152. {
  153.   return getstr (lineptr, n, stream, delimiter, 0);
  154. }
  155. #endif
  156.